/**
 * @Author       : Mo 2427995270@qq.com
 * @Date         : 2025-07-31 00:56:39
 * @LastEditTime : 2025-08-01 00:30:02
 * @FilePath     : \ZN-1000-APP\hal_driver\ll_rtc.c
 * @Description  : RTC低层驱动
 * @Version      : V1.0
 * @History      :
 * @Note         :
 */
/***************************************Includes***********************************/
#include "ll_rtc.h"
#include <string.h>

#if defined(GD32F407)
#include "gd32f4xx.h"
#elif defined(GD32F10X_HD)
#include "gd32f10x.h"
#elif defined(STM32F10X_HD)
#include "stm32f10x.h"
#elif defined(STM32F40_41xxx)
#include "stm32f4xx.h"
#elif defined(PY32F071xB)
#include "py32f0xx.h"
#else
#error "No device selected"
#endif

/************************************Private Macros********************************/
// #define


/**********************************Private Statement*******************************/

#if defined(PY32F071xB)
static HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef *hrtc);
static HAL_StatusTypeDef RTC_ExitInitMode(RTC_HandleTypeDef *hrtc);
#endif

/***********************************Public Variables*******************************/



/**********************************Private Variables*******************************/

static rtc_ll_t *rtc_handle;

/**********************************Public Functions********************************/

void rtc_ll_init(rtc_ll_t *rtc) {
    rtc_handle = rtc;
#if defined(PY32F071xB)
    RTC_HandleTypeDef *handle = (void *)rtc->rtc;
    handle->Instance = RTC;
    handle->Init.AsynchPrediv = RTC_AUTO_1_SECOND;
    handle->Init.OutPut = RTC_OUTPUTSOURCE_NONE;
    RCC_OscInitTypeDef RCC_OscInit = {0};
    RCC_PeriphCLKInitTypeDef PeriphClkInsit = {0};

    RCC_OscInit.OscillatorType = RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI;
    RCC_OscInit.PLL.PLLState = RCC_PLL_NONE;
    RCC_OscInit.LSEState = RCC_LSE_ON;
    RCC_OscInit.LSEDriver = RCC_LSEDRIVE_MEDIUM;
    RCC_OscInit.LSIState = RCC_LSI_OFF;
    if (HAL_RCC_OscConfig(&RCC_OscInit) != HAL_OK) {
        RCC_OscInit.LSIState = RCC_LSI_ON;
        RCC_OscInit.LSEState = RCC_LSE_OFF;
        HAL_RCC_OscConfig(&RCC_OscInit);
    }
    PeriphClkInsit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
    PeriphClkInsit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInsit) != HAL_OK) {
    }
    __HAL_RCC_RTCAPB_CLK_ENABLE();
    __HAL_RCC_RTC_ENABLE();
    NVIC_SetPriority(RTC_IRQn, rtc->cfg_interrupt_priority);
    NVIC_EnableIRQ(RTC_IRQn);
    __HAL_RTC_SECOND_ENABLE_IT(handle, RTC_IT_SEC);
    if (HAL_RTC_Init(handle) != HAL_OK) {
        for (;;)
            ;
    }
    uint16_t high1 = 0U, high2 = 0U, low = 0U;

    high1 = READ_REG(handle->Instance->CNTH & RTC_CNTH_RTC_CNT);
    low = READ_REG(handle->Instance->CNTL & RTC_CNTL_RTC_CNT);
    high2 = READ_REG(handle->Instance->CNTH & RTC_CNTH_RTC_CNT);

    if (high1 != high2) {
        /* In this case the counter roll over during reading of CNTL and CNTH registers,
           read again CNTL register then return the counter value */
        rtc->t = (((uint32_t)high2 << 16U) | READ_REG(handle->Instance->CNTL & RTC_CNTL_RTC_CNT));
    } else {
        /* No counter roll over during reading of CNTL and CNTH registers, counter
           value is equal to first value of CNTL and CNTH */
        rtc->t = (((uint32_t)high1 << 16U) | low);
    }

#endif
}
/**
 * @brief 设置日期时间
 * @param  rtc
 * @param  t                时间戳 可为NULL
 * @param  tm               时间结构体 可为NULL
 * @return int 0成功 -1失败
 * @note t 和 tm 二选一
 */
int rtc_set_date_time(rtc_ll_t *rtc, time_t *t, struct tm *tm) {
#if defined(PY32F071xB)
    RTC_HandleTypeDef *hrtc = (void *)rtc->rtc;
    if (RTC_EnterInitMode(hrtc) != HAL_OK) {
        return -1;
    } else {
        if (t) {
            /* Set RTC COUNTER MSB word */
            WRITE_REG(hrtc->Instance->CNTH, (*t >> 16U));
            /* Set RTC COUNTER LSB word */
            WRITE_REG(hrtc->Instance->CNTL, (*t & RTC_CNTL_RTC_CNT));
            rtc->t = *t;
            time_t _t = rtc->t + 8 * 60 * 60;
            localtime_r(&_t, &rtc->tm);
        }
        if (tm) {
            rtc->t = mktime(tm) - 8 * 60 * 60;
            rtc->tm = *tm;
            /* Set RTC COUNTER MSB word */
            WRITE_REG(hrtc->Instance->CNTH, (rtc->t >> 16U));
            /* Set RTC COUNTER LSB word */
            WRITE_REG(hrtc->Instance->CNTL, (rtc->t & RTC_CNTL_RTC_CNT));
        }
        /* Wait for synchro */
        if (RTC_ExitInitMode(hrtc) != HAL_OK) {
            return -1;
        }
    }
    return 0;
#endif
    return -1;
}
/**
 * @brief 获取时间戳 本地UTC+8
 * @param  rtc              
 * @return time_t 时间戳
 * @note null
 */
time_t rtc_get_timestamp(rtc_ll_t *rtc) {
    return rtc->t;
}
/**
 * @brief 获取时间日期
 * @param  rtc              
 * @return struct tm* 时间结构体指针
 * @note null
 */
struct tm *rtc_get_date_time(rtc_ll_t *rtc) {
    time_t t = rtc->t + 8 * 60 * 60;
    localtime_r(&t, &rtc->tm);
    return &rtc->tm;
}
/**
 * @brief 时间日期转时间戳
 * @param  tm               
 * @return time_t 
 * @note null
 */
time_t rtc_date_time_to_timestamp(struct tm *tm) {
    return mktime(tm) - 8 * 60 * 60;
}
/**
 * @brief 时间戳转时间日期
 * @param  t                
 * @return struct tm* 
 * @note null
 */
struct tm *rtc_timestamp_to_date_time(time_t t) {
    static struct tm _tm;
    t = t + 8 * 60 * 60;
    localtime_r(&t, &_tm);
    return &_tm;
}
/**
 * @brief 时间日期转字符串 format格式同strftime
 * @param  tm               
 * @param  format           格式化时间字符串
 * @param  buf              线程安全支持的缓冲区
 * @param  size             缓冲区大小
 * @return const char* 时间字符串 非线程安全
 * @note null
 */
const char *rtc_data_time_to_str(struct tm *tm, const char *format, void *buf, int size) {
    static char str[32];
    strftime(str, sizeof(str), format, tm);
    if (buf)
        strncpy(buf, str, size);
    return str;
}

#if defined(PY32F071xB)
void RTC_IRQHandler(void) {
    RTC_HandleTypeDef *hrtc = (void *)rtc_handle->rtc;
    if (__HAL_RTC_SECOND_GET_IT_SOURCE(hrtc, RTC_IT_SEC)) {
        /* Get the status of the Interrupt */
        if (__HAL_RTC_SECOND_GET_FLAG(hrtc, RTC_FLAG_SEC)) {
            /* Check if Overrun occurred */
            if (__HAL_RTC_SECOND_GET_FLAG(hrtc, RTC_FLAG_OW)) {
                /* Second error callback */
                // HAL_RTCEx_RTCEventErrorCallback(hrtc);

                /* Clear flag Second */
                __HAL_RTC_OVERFLOW_CLEAR_FLAG(hrtc, RTC_FLAG_OW);

                /* Change RTC state */
                hrtc->State = HAL_RTC_STATE_ERROR;
            } else {
                /* Second callback */
                // HAL_RTCEx_RTCEventCallback(hrtc);
                rtc_handle->t++;

                /* Change RTC state */
                hrtc->State = HAL_RTC_STATE_READY;
            }

            /* Clear flag Second */
            __HAL_RTC_SECOND_CLEAR_FLAG(hrtc, RTC_FLAG_SEC);
        }
    }
    if (__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRA)) {
        /* Get the status of the Interrupt */
        if (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) != (uint32_t)RESET) {
            /* AlarmA callback */
            // HAL_RTC_AlarmAEventCallback(hrtc);

            /* Clear the Alarm interrupt pending bit */
            __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
        }
    }
}
#endif

/**********************************Private Functions*******************************/


#if defined(PY32F071xB)

/**
 * @brief  Enters the RTC Initialization mode.
 * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
 *                the configuration information for RTC.
 * @retval HAL status
 */
static HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef *hrtc) {
    uint32_t tickstart = 0U;

    tickstart = HAL_GetTick();
    /* Wait till RTC is in INIT state and if Time out is reached exit */
    while ((hrtc->Instance->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET) {
        if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE) {
            return HAL_TIMEOUT;
        }
    }

    /* Disable the write protection for RTC registers */
    __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);


    return HAL_OK;
}

/**
 * @brief  Exit the RTC Initialization mode.
 * @param  hrtc   pointer to a RTC_HandleTypeDef structure that contains
 *                the configuration information for RTC.
 * @retval HAL status
 */
static HAL_StatusTypeDef RTC_ExitInitMode(RTC_HandleTypeDef *hrtc) {
    uint32_t tickstart = 0U;

    /* Disable the write protection for RTC registers */
    __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);

#if (defined(PY32F030PRE) || defined(PY32F003PRE) || defined(PY32F002APRE))
    tickstart = HAL_GetTick();
    /* Wait till RTC is in NOINIT state and if Time out is reached exit */
    while ((hrtc->Instance->CRL & RTC_CRL_RTOFF) == RTC_CRL_RTOFF) {
        if ((HAL_GetTick() - tickstart) > RTC_RTOFF_RESET_TIMEOUT_VALUE) {
            break;
        }
    }
#endif /* PY32F030PRE or PY32F003PRE or PY32F002APRE */

    tickstart = HAL_GetTick();
    /* Wait till RTC is in INIT state and if Time out is reached exit */
    while ((hrtc->Instance->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET) {
        if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE) {
            return HAL_TIMEOUT;
        }
    }

    return HAL_OK;
}

#endif
/* [] END OF FILE */
